package com.xebest.util;


import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 操作EXCEL共用类
 *
 * @author 赵盼飞
 */
@SuppressWarnings("rawtypes")
public class XeVenExcelUtil {

    private static final Logger log = Logger.getLogger(XeVenExcelUtil.class);

    // 替换生成的excel对象
    HSSFWorkbook workbook = null;
    // xsl模板文件
    String templateFile = "";
    // 目标文件
    String xslFile = "";
    // 模板文件夹路径
    String tmpDir = null;
    // 输出xsl文件夹路径
    String xlsDir = null;
    // 数据集合
    List dataList = null;
    // 数据Map
    Map dataMap = null;
    // excel模版里需要替换的CodeField信息集合
    ArrayList codes = null;
    // 错误信息
    String errMsg = "err";

    HSSFDataFormat format;

    HSSFFont font;

    /**
     * 构造函数
     */
    public XeVenExcelUtil() {
        super();
        if (log.isDebugEnabled()) {
            log.debug("TradeEntityToExcel 构造成功，模板路径：" + tmpDir + " 输出路径："
                    + xlsDir);
        }

    }

    /**
     * 构造函数
     *
     * @param xlsDir ：报表输出文件的文件夹路径
     */
    public XeVenExcelUtil(String xlsDir) {
        super();
        // 模板路径
        this.xlsDir = xlsDir;
        if (log.isDebugEnabled()) {
            log.debug("TradeEntityToExcel 构造成功，输出路径：" + xlsDir);
        }
    }

    /**
     * 构造函数
     *
     * @param tmpDir ：报表模板的文件夹路径
     * @param xlsDir ：报表输出文件的文件夹路径
     */
    public XeVenExcelUtil(String tmpDir, String xlsDir) {
        super();
        // 模板路径
        this.tmpDir = tmpDir;
        this.xlsDir = xlsDir;
        if (log.isDebugEnabled()) {
            log.debug("TradeEntityToExcel 构造成功，模板路径：" + tmpDir + " 输出路径："
                    + xlsDir);
        }
    }

    /**
     * 构造函数
     *
     * @param tmpDir       ：报表模板的文件夹路径
     * @param xlsDir       ：报表输出文件的文件夹路径
     * @param templateFile ：模板文件
     */
    public XeVenExcelUtil(String tmpDir, String xlsDir, String templateFile) {
        super();
        // 模板路径
        this.tmpDir = tmpDir;
        this.xlsDir = xlsDir;
        this.templateFile = templateFile;
        if (log.isDebugEnabled()) {
            log.debug("TradeEntityToExcel 构造成功，模板路径：" + tmpDir + " 输出路径："
                    + xlsDir + " 模板文件：" + templateFile);
        }
    }

    private void setErrMsg(String errMsg) {
        this.errMsg = "err-->>" + errMsg;
    }

    /**
     * 得到模版文件标记域信息(excel模版里需要替换的CodeField信息集合)
     */
    @SuppressWarnings({"unchecked", "resource"})
    private void getExcelCodeList(String xlsName) throws Exception {
        POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(xlsName));
        HSSFWorkbook outwb = new HSSFWorkbook(fs);

        String cellmsg = "";
        codes = new ArrayList();
        int sheetCount = this.dataList.size() / 65535 + 1;
        // 遍历工作薄
        for (int i = 0; i < sheetCount; i++) {// one sheet
            HSSFSheet outsheet = outwb.getSheetAt(i);

            // 遍历工作行
            for (int j = 0; j <= outsheet.getLastRowNum(); j++) {
                HSSFRow outrow = (HSSFRow) outsheet.getRow(j);
                if (outrow == null)
                    continue;
                // 获取列
                for (int k = 0; k <= outrow.getLastCellNum(); k++) {

                    HSSFCell outcell = (HSSFCell) outrow.getCell((short) k);
                    cellmsg = getExcelCellValue(outcell);
                    if (cellmsg.startsWith("#") || cellmsg.startsWith("%")
                            || cellmsg.startsWith("&")) {
                        codes.add(new CodeField(cellmsg, i, j, k));
                    }
                }

            }
        }

    }

    /**
     * 为模版文件存副本
     *
     * @param source 模板文件路径
     * @param dest   副本文件路径
     *               void
     * @author 赵盼飞
     */
    @SuppressWarnings("resource")
    private void doSaveAs(String source, String dest) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(dest);
            POIFSFileSystem fs = new POIFSFileSystem(
                    new FileInputStream(source));
            HSSFWorkbook wb = new HSSFWorkbook(fs);
            wb.write(fos);
        } catch (Exception e) {
            log.error(e);
        } finally {
            try {
                fos.close();
            } catch (Exception ei) {
                ei.printStackTrace();
            }
        }
    }

    /**
     * 替换baseinfo信息 # 表示单值，在模版中不允许重复
     *
     * @param strDest
     * @param codes
     */
    private void exportBaseInfo() {
        for (int i = 0; i < codes.size(); i++) {

            CodeField field = (CodeField) codes.get(i);
            if (field.getCode().startsWith("&")) {
                Object obj = dataMap.get(field.getCode().substring(1));
                String newValue = "";
                if (obj != null) {
                    newValue = obj.toString();
                }
                // 写入标题头列
                setExcelCell(field.getSheet(), 0, field.getCol(),
                        newValue);
            }
        }
    }

    /**
     * 为单元格的创建样式与值
     *
     * @author 赵盼飞
     */
    private void setExcelCell(int isheet, int irow, int icol, String newValue) {
        try {
            HSSFCell cell = null;
            HSSFSheet sheet = workbook.getSheetAt(isheet);
            // 判断行是否存在,如果不存在则建立一行
            HSSFRow row = sheet.getRow(irow);

            if (row == null) {
                row = sheet.createRow(irow);
            }
            cell = row.getCell((short) icol);
            if (cell == null) {
                cell = row.createCell((short) icol);
            }
            setExcelCellValue(cell, newValue);
        } catch (Exception e) {
            log.error(e);
        }
    }


    /**
     * 为单元格写入值
     *
     * @param outcell  单元格
     * @param newValue 值
     *                 void
     * @author 赵盼飞
     */
    private void setExcelCellValue(HSSFCell outcell, String newValue) {
        if (outcell == null) {
            return;
        }
        boolean flag = false;
        double value = 0;
        if (flag == true) {
            outcell.setCellValue(value);
        } else {
            outcell.setCellValue(newValue);
        }
    }

    @SuppressWarnings("deprecation")
    private String getExcelCellValue(HSSFCell outcell) {
        String cellmsg = "";
        if (outcell == null) {
            return "";
        }
        switch (outcell.getCellType()) {
            case HSSFCell.CELL_TYPE_BLANK:
                cellmsg = outcell.getStringCellValue();
                break;
            case HSSFCell.CELL_TYPE_BOOLEAN:
                cellmsg = String.valueOf(outcell.getBooleanCellValue());
                break;
            case HSSFCell.CELL_TYPE_ERROR:
                break;
            case HSSFCell.CELL_TYPE_FORMULA:
                break;
            case HSSFCell.CELL_TYPE_NUMERIC:
                cellmsg = String.valueOf(outcell.getNumericCellValue());
                break;
            case HSSFCell.CELL_TYPE_STRING:
                cellmsg = outcell.getStringCellValue();
                break;
            default:
                cellmsg = outcell.getStringCellValue();
        }
        return cellmsg;
    }

    /**
     * 打开要替换的excel文件
     */
    private void openExcel(String excelName) throws Exception {
        POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(excelName));
        workbook = new HSSFWorkbook(fs);
        format = workbook.createDataFormat();
        font = workbook.createFont();
    }

    /**
     * 保存需要替换的excel文件
     */
    private void saveExcel(String excelName) throws Exception {
        FileOutputStream fileOut = new FileOutputStream(excelName);
        workbook.write(fileOut);
        fileOut.close();

    }

    /**
     * 将excel输出到制定的流中
     */
    @SuppressWarnings("unused")
    private void saveExcel(OutputStream os) throws Exception {
        workbook.write(os);
    }

    /**
     * 加入制定sheet的一个空行
     */
    @SuppressWarnings("unused")
    private void insertBlankRow(int isheet, int beginRow) {
        // sheet循环
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            HSSFSheet sheet = workbook.getSheetAt(i);

            if (isheet == i) {
                // 1,指定行后插入移行
                int lastRowNum = sheet.getLastRowNum();
                System.out.println("lastRowNum: " + lastRowNum);
                HSSFRow lastRow_1 = sheet.getRow(lastRowNum);
                // 创建新的最后一行，将最后一行内容复制到新的行
                HSSFRow lastRow = sheet.createRow(beginRow + 1);
                for (int l = 0; l < 20; l++) {
                    HSSFCell lcell = lastRow_1.getCell((short) l);
                    HSSFCell ncell = lastRow.createCell((short) l);
                }
            }
        }
    }

    /**
     * 替换Detail域的信息 循环数据处理，第一层
     *
     * @param flag 标识是1:List<T>类型还是2:List<Map>类型
     *             void
     * @author 赵盼飞
     */
    @SuppressWarnings({"unchecked"})
    private void exportDetail(int flag) throws Exception {

        CodeField onefield = null; // detail中%的域
        ArrayList rows = new ArrayList();
        // 纵向输出取标签集合
        for (int i = 0; i < codes.size(); i++) {
            CodeField field = (CodeField) codes.get(i);
            // 循环体节点
            if (field.getCode().startsWith("%")) {
                onefield = field;
            }
            // 纵向明细输出
            if (field.getCode().startsWith("&")) {
                rows.add(field);
            }
        }
        // 替换掉%的域
        if (onefield != null) {
            setExcelCell(onefield.getSheet(), onefield.getRow(),
                    onefield.getCol(), "");
        }

        if (flag == 1) {
            exportDataListEntity(dataList, rows);
        } else {
            exportDataListMap(dataList, rows);
        }

    }

    /**
     * 替换Detail域的信息 循环数据处理，第2层
     */
    @SuppressWarnings({"unused"})
    private void exportDataListMap(List dList, ArrayList rows) {
        // 取出欲替换的行数 details.length,替换模版位置
        // 定位起始坐标
        CodeField field = null;
        if (rows.size() > 0) {
            field = (CodeField) rows.get(0);
        }
        int b = 0;
        for (int i = 0; i < dList.size(); i++) {

            if (i > 0 && i % 65535 == 0) {
                b++;
            }
            HashMap hash = (HashMap) dList.get(i);

            for (int l = 0; l < rows.size(); l++) {
                CodeField filed = (CodeField) rows.get(l);
                // 工作薄
                int sheet = b;//filed.getSheet();
                // 当前行
                int setRows = filed.getRow() + (i - b * 65535);
                // 当前列
                int setCols = filed.getCol();
                // 列头变量
                String code = filed.getCode().toUpperCase();
                code = code.substring(1);
                // 获取值
                Object value = hash.get(code);
                // String value = (String) hash.get(code);
                setExcelCell(sheet, setRows, setCols, value == null ? "" : value.toString());
            }
        }
    }


    /**
     * 替换Detail域的信息 循环数据处理，第2层
     */
    @SuppressWarnings({"unused"})
    private void exportDataListEntity(List<T> dList, ArrayList rows) throws Exception {
        // 取出欲替换的行数 details.length,替换模版位置
        // 定位起始坐标
        CodeField field = null;
        if (rows.size() > 0) {
            field = (CodeField) rows.get(0);
        }
        int b = 0;
        //如果数据为空，删除模板中的第二行数据
        if (dList == null || dList.size() == 0) {
            HSSFSheet sheet = workbook.getSheetAt(field.getSheet());
            HSSFRow row = sheet.getRow(1);
            sheet.removeRow(row);
        }
        for (int i = 0; i < dList.size(); i++) {

            if (i > 0 && i % 65535 == 0) {
                b++;
            }
            Object obj = dList.get(i);
            for (int l = 0; l < rows.size(); l++) {
                CodeField field1 = (CodeField) rows.get(l);
                //获取到get方法的名字
                String getMethodName = "get" + field1.getCode().substring(1, 2).toUpperCase() + field1.getCode().substring(2);
                // 工作薄
                int sheet = b;//filed.getSheet();
                // 当前行
                int setRows = field1.getRow() + (i - b * 65535);
                // 当前列
                int setCols = field1.getCol();
                // 获取值
                Method getMethod = obj.getClass().getMethod(getMethodName, new Class[]{});
                Object value = getMethod.invoke(obj, new Class[]{});
                setExcelCell(sheet, setRows, setCols, value == null ? ""
                        : value.toString());
            }
        }

    }

    /**
     * 获取yyyyMMddhhmmss字符串
     *
     * @author 赵盼飞
     */
    public static String getCurDateStrTemName() {
        Calendar cal = GregorianCalendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat();
        try {
            String pattern = "yyyyMMddhhmmss";
            sdf.applyPattern(pattern);
            String s = sdf.format(cal.getTime()) + System.currentTimeMillis();
            return s;

        } catch (Exception e) {
            log.error(e);
            return "19000101";
        }

    }

    /**
     * 根据模板文件将交易数据 TrEntity 转换XSL文件
     *
     * @param dataMap      标题内容(传入可为标题设置样式，k为field;v为field对应标题头)
     * @param dataList     数据
     * @param templateFile 模板名称
     * @param FExcelName   输出文件名称
     * @param flag         传入类型标识:1:List<T>类型还是2:List<Map>类型
     * @return String 结果文件
     * @author 赵盼飞
     */
    public String generateExcelByTemplate(Map dataMap, List dataList, String templateFile, String FExcelName, int flag) {
        //文件夹不存在创建
        if (!IsFolderExists(tmpDir)) {
            createFolder(tmpDir);
        }
        if (!IsFolderExists(xlsDir)) {
            createFolder(xlsDir);
        }
        // 源数据
        this.dataList = dataList;
        this.dataMap = dataMap;

        //模板文件路径
        String srcfile = tmpDir + templateFile;

        File tempFile = new File(srcfile);
        log.info(("  srcfile:" + srcfile));
        //模板不存在创建
        if (!tempFile.exists()) {
            log.error("模板文件[" + srcfile + "]不存在，系统将自动创建该模板！");
            this.setErrMsg("template is not exit！" + srcfile);
            // 创建文件
            try {
                //创建XLS文件
                CreateXL(srcfile);
                //打开要替换的XLS文件
                openExcel(srcfile);
                //保存SLX文件
                saveExcel(srcfile);
            } catch (Exception e) {
                log.error(e);
                log.error("创建模板文件[" + srcfile + "]异常：" + e.getMessage());
            }
        }

        String strDest = "";
        // 输出文件名不存在创建
        if ("".equals(FExcelName) || FExcelName == null) {
            FExcelName = getCurDateStrTemName() + templateFile + ".xls";
        }
        strDest = xlsDir + FExcelName;
        // 另存模板excel
        doSaveAs(srcfile, strDest);

        // log.info("doSaveAs---->>");
        try {
            // 获取输出变量的行(codes)
            getExcelCodeList(strDest);

            // 打开另存的excel
            openExcel(strDest);
            // 写入带样式的头信息
            if (null != dataMap) {
                exportBaseInfo();
            }
            //写入数据
            exportDetail(flag);
            //保存XLS到指定文件
            saveExcel(strDest);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("xls输出异常:" + e.getMessage());
        }
        return FExcelName;
    }

    /**
     * 文件的写入 将要分行的数组以数组的形式传入
     *
     * @param filePath (文件路径)
     * @param args     []
     */
    public void writeFile(String filePath, String[] args) throws IOException {
        FileWriter fw = new FileWriter(filePath);
        PrintWriter out = new PrintWriter(fw);
        for (int i = 0; i < args.length; i++) {
            out.write(args[i]);
            out.println();
        }
        fw.close();
        out.close();
    }

    public boolean IsFolderExists(String filePath) {
        File file = new File(filePath);
        return file.exists();
    }

    /**
     * 新建目录
     *
     * @param folderPath 目录路径
     * @return String 返回目录创建后的路径
     * @author 赵盼飞
     */
    public String createFolder(String folderPath) {
        String txt = folderPath;
        try {
            java.io.File myFilePath = new java.io.File(txt);
            txt = folderPath;
            if (!myFilePath.exists()) {
                myFilePath.mkdir();
            }
        } catch (Exception e) {
        }
        return txt;
    }

    /**
     * 判断文件是否存在
     */

    public boolean IsFileExists(String filePath) {
        File f = new File(filePath);
        return f.exists();
    }

    /**
     * 创建XLS文件
     */
    @SuppressWarnings("deprecation")
    public void CreateXL(String outputFile) {
        try {
            // 创建新的Excel 工作簿
            if (workbook == null) {
                workbook = new HSSFWorkbook();
            }
            HSSFSheet sheet = workbook.createSheet();
            // 在索引0的位置创建行（最顶端的行）
            HSSFRow row = sheet.createRow((short) 0);
            // 在索引0的位置创建单元格（左上端）
            HSSFCell cell = row.createCell((short) 0);
            // 定义单元格为字符串类型
            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
            // 在单元格中输入一些内容
            cell.setCellValue("");
            // 新建一输出文件流
            FileOutputStream fOut = new FileOutputStream(outputFile);
            // 把相应的Excel 工作簿存盘

            // 加入空行
            for (int i = 0; i < 2; i++) {
                insertBlankRow(0, i);// 加入一个新行
            }
            workbook.write(fOut);
            fOut.flush();
            // 操作结束，关闭文件
            fOut.close();
            log.info("XLS文件创建成功！FILE:" + outputFile);
        } catch (Exception e) {
            log.error("创建xls文件失败:" + e.getMessage());
        }
    }

    /**
     * 删除文件
     *
     * @param path 文件路径
     * @return boolean
     * @author 赵盼飞
     */
    public static boolean deleteFolder(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        } else {
            file.delete();
            flag = true;
        }
        return flag;
    }


    public static void download(String path, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename="
                    + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(
                    response.getOutputStream());
            if (path.indexOf(".zip") > 0) {
                response.setContentType("application/zip");// 定义输出类型
            } else {
                response.setContentType("application/vnd.ms-excel;charset=gb2312");
            }
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
            if (file.exists()) {
                file.delete();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 创建模板文件
     *
     * @param heads  标题内容
     * @param fields 属性名称
     * @return 模板创建路径
     * @author 赵盼飞
     */
    @SuppressWarnings("resource")
    public String createTemplet(List<String> heads, String[] fields) throws IOException {
        Workbook wb = new HSSFWorkbook();
        int rowIndex = 0;
        Sheet sheet = wb.createSheet();
        Row row = sheet.createRow(rowIndex++);//创建第一行
        for (int i = 0; i < heads.size(); i++) {
            //创建标题头单元格
            row.createCell(i).setCellValue(heads.get(i));
        }
        row = sheet.createRow(rowIndex++);//创建第二行
        for (int j = 0; j < fields.length; j++) {
            //创建field单元格
            row.createCell(j).setCellValue("&" + fields[j]);
        }
        //模板存放位置，tmpDir文件夹，模板名字
        FileOutputStream fs = new FileOutputStream(tmpDir + templateFile);
        wb.write(fs);
        fs.close();
        return tmpDir + templateFile;
    }


    /**
     * 计算出总页数
     *
     * @param countSize 总记录数
     * @param pageSize  每页条数
     * @return Integer
     * @author 赵盼飞
     */
    public static Integer getPageCount(Integer countSize, Integer pageSize) {
        return (countSize + pageSize - 1) / pageSize;
    }


    /**
     * 根据传入字段获取导出标题
     *
     * @param obj 导出对应的DTO实例
     * @author 赵盼飞
     */
    public static List<String> getheadList(Object obj, String[] paraArr) throws Exception {
        List<String> fieldList = new ArrayList<String>();
        for (int j = 0; j < paraArr.length; j++) {
            Field field = obj.getClass().getDeclaredField(paraArr[j]);
            System.out.println(field);
            if (!StringUtils.isEmpty(field.getAnnotation(XeVenColumnName.class))) {
                fieldList.add(field.getAnnotation(XeVenColumnName.class).value());
            }
        }
        return fieldList;
    }

    /**
     * @param list        数据
     * @param entity      导出实体DTO
     * @param fieldArr    导出的字段
     * @param templetDir  末班路径
     * @param outFileName 导出文件名
     * @author 赵盼飞
     */
    public static <N, E> boolean exportExcelService(List<N> list, E entity, String[] fieldArr, String templetDir, String outFileName, HttpServletResponse response) {
        boolean flag = false;
        List<String> headList = null;
        try {
            headList = XeVenExcelUtil.getheadList(entity, fieldArr);
        } catch (Exception e1) {
            log.info("-------获取标题头失败----{}", e1);
        }
        String templetFileName = getCurDateStrTemName() + "_xe_ven_export_templet.xls";//模板名
        XeVenExcelUtil excelUtil = new XeVenExcelUtil(templetDir, templetDir, templetFileName);
        String tempPath = null;//模板生成位置
        try {
            tempPath = excelUtil.createTemplet(headList, fieldArr);
        } catch (IOException e) {
            log.info("-------创建模板失败------{}", e);
        }
        outFileName = outFileName + DateTime.now().toString("yyyyMMdd") + "-" + System.currentTimeMillis() + ".xls";
        //生成excel文件
        excelUtil.generateExcelByTemplate(null, list, templetFileName, outFileName, 1);
        //下载生成的文件
        XeVenExcelUtil.download(templetDir + outFileName, response);
        //模板使用完成进行删除
        XeVenExcelUtil.deleteFolder(tempPath);
        flag = true;
        return flag;
    }


    /**
     * 根据List<List<Object>> 传入数据生成EXCEL
     *
     * @author 赵盼飞
     */
    @SuppressWarnings("resource")
    public String createExcelByLists(List<List<Object>> listObjs, String fileName) throws IOException {
        Workbook wb = new HSSFWorkbook();
        Sheet sheet = wb.createSheet();
        Row row = null;
        for (int i = 0; i < listObjs.size(); i++) {
            List<Object> objs = listObjs.get(i);
            row = sheet.createRow(i);//创建行
            for (int j = 0; j < objs.size(); j++) {
                row.createCell(j).setCellValue(objs.get(j) + "");
            }
        }
        //EXCEL存放位置，xlsDir文件夹
        FileOutputStream fs = new FileOutputStream(xlsDir + fileName);
        wb.write(fs);
        fs.close();
        return xlsDir + fileName;
    }


}

/**
 * 说明:得出excel模版的替换域
 *
 * @author xebest
 */
class CodeField {

    public CodeField(String code, int sheet, int row, int col) {
        this.sheet = sheet;
        this.code = code;
        this.row = row;
        this.col = col;
    }

    private int sheet = 0;
    private int row = 0;
    private int col = 0;
    private String code;

    /**
     * @return Returns the sheet.
     */
    public int getSheet() {
        return sheet;
    }

    /**
     * @param sheet The sheet to set.
     */
    public void setSheet(int sheet) {
        this.sheet = sheet;
    }

    /**
     * @return Returns the code.
     */
    public String getCode() {
        return code;
    }

    /**
     * @param code The code to set.
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @return Returns the col.
     */
    public int getCol() {
        return col;
    }

    /**
     * @param col The col to set.
     */
    public void setCol(int col) {
        this.col = col;
    }

    /**
     * @return Returns the row.
     */
    public int getRow() {
        return row;
    }

    /**
     * @param row The row to set.
     */
    public void setRow(int row) {
        this.row = row;
    }

}